package model.pieces;

import java.awt.Point;
import java.util.LinkedList;
import java.util.List;

import utils.PlayerSides;

import model.Board;

/**
 * Class represents the Rook piece in chess game. A Bishop can move forward, backward, right and left, until reaches another piece.
 */
public class Rook extends Piece {

	// protected methods
	
	/**
	 * Gets reference to the game board and Rooks's current position on board.
	 * Returns a list of all positions that hold an opponent's piece and lay on path in any straight direction	 
	 */
	@Override
	protected List<Point> getAvailableFreePositions(Board gameBoard, Point srcPoint) {
		
		// initialize free possible positions list
		List<Point> freeList = new LinkedList<Point>();
		
		// initialize current row and column to search
		int currRow = srcPoint.x + getDirection();
		int currCol = srcPoint.y;
		
		// scan forward path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));			
			// move to next position
			currRow += getDirection();
		}
		
		// initialize current row and column to search
		currRow = srcPoint.x - getDirection();
		
		// scan backward path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));			
			// move to next position
			currRow -= getDirection();
		}
				
		// initialize current row and column to search
		currRow = srcPoint.x;
		currCol = srcPoint.y + getDirection();
		
		// scan right path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));			
			// move to next position
			currCol += getDirection();
		}
		
		// initialize current row and column to search
		currCol = srcPoint.y - getDirection();
		
		// scan left path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));
			
			// move to next position
			currCol -= getDirection();
		}
		
		// return list of position in range found
		return freeList;
	}

	/**
	 * Gets reference to the game board and Rooks's current position on board.
	 * Returns a list of all positions holding opponent's pieces, that lay on a clear path in any straight direction	 
	 */
	@Override
	protected List<Point> getAvailableOpponentPositions(Board gameBoard, Point srcPoint) {
		
		// initialize list of reachable opponent's positions
		List<Point> opponentList = new LinkedList<Point>();
		
		// initialize current row and column to search
		int currRow = srcPoint.x + getDirection();
		int currCol = srcPoint.y;
		
		// scan forward path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {

			// move to next position
			currRow += getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameSide(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}
		
		// initialize current row and column to search
		currRow = srcPoint.x - getDirection();
		
		// scan backward path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// move to next position
			currRow -= getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameSide(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}

		
		// initialize current row and column to search
		currRow = srcPoint.x;
		currCol = srcPoint.y + getDirection();
		
		// scan right path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
						
			// move to next position
			currCol += getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameSide(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}

		
		// initialize current row and column to search
		currCol = srcPoint.y - getDirection();
		
		// scan left path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
						
			// move to next position
			currCol -= getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameSide(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}

		
		// return list of position in range found
		return opponentList;
	}

	// public methods
	
	/**
	 * Constructor- creates a new Tower assigned to given player
	 * @param side- indicates piece's player
	 */
	public Rook(PlayerSides.Sides side) {
		super(side);
	}
	
	/**
	 * Returns a Rook of the same team
	 */
	@Override
	public Piece clone() { return new Rook(super.getPlayer()); }
}